<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>游戏虚拟摇杆示例</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background: #2c3e50;
            font-family: Arial, sans-serif;
            color: #ecf0f1;
            overflow: hidden;
            touch-action: none;
        }
        #gameCanvas {
            background: #34495e;
            border: 2px solid #ecf0f1;
            margin-bottom: 20px;
        }
        #joystickContainer {
            position: relative;
            width: 200px;
            height: 200px;
        }
        #joystickBase {
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.2);
            border-radius: 50%;
            position: absolute;
            top: 0;
            left: 0;
        }
        #joystickHandle {
            width: 50px;
            height: 50px;
            background: rgba(255, 255, 255, 0.9);
            border-radius: 50%;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            cursor: move;
        }
        #output {
            margin-top: 20px;
            padding: 15px;
            background: rgba(0, 0, 0, 0.3);
            border-radius: 10px;
            text-align: center;
            width: 300px;
        }
        h1 {
            margin-bottom: 20px;
            text-align: center;
        }
        .instructions {
            margin: 15px 0;
            padding: 10px;
            background: rgba(0, 0, 0, 0.2);
            border-radius: 5px;
            text-align: center;
        }
    </style>
</head>
<body>
    <h1>HTML5虚拟摇杆演示</h1>
    
    <canvas id="gameCanvas" width="300" height="300"></canvas>
    
    <div class="instructions">使用鼠标或触摸拖动摇杆控制角色移动</div>
    
    <div id="joystickContainer">
        <div id="joystickBase"></div>
        <div id="joystickHandle"></div>
    </div>
    
    <div id="output">
        <p>摇杆输出值：</p>
        <p>X: <span id="xValue">0</span></p>
        <p>Y: <span id="yValue">0</span></p>
        <p>角度: <span id="angle">0</span>°</p>
        <p>强度: <span id="intensity">0</span></p>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // 获取元素引用
            const joystickBase = document.getElementById('joystickBase');
            const joystickHandle = document.getElementById('joystickHandle');
            const joystickContainer = document.getElementById('joystickContainer');
            const xValueElement = document.getElementById('xValue');
            const yValueElement = document.getElementById('yValue');
            const angleElement = document.getElementById('angle');
            const intensityElement = document.getElementById('intensity');
            const gameCanvas = document.getElementById('gameCanvas');
            const ctx = gameCanvas.getContext('2d');
            
            // 游戏角色属性
            const player = {
                x: gameCanvas.width / 2,
                y: gameCanvas.height / 2,
                radius: 15,
                color: '#e74c3c',
                speed: 3
            };
            
            // 摇杆属性
            const joystick = {
                baseRadius: 100,
                handleRadius: 25,
                maxDistance: 75, // 摇杆最大移动距离
                x: 0,
                y: 0,
                isActive: false
            };
            
            // 初始化游戏绘制
            function drawGame() {
                // 清空画布
                ctx.clearRect(0, 0, gameCanvas.width, gameCanvas.height);
                
                // 绘制网格背景
                drawGrid();
                
                // 绘制玩家角色
                ctx.beginPath();
                ctx.arc(player.x, player.y, player.radius, 0, Math.PI * 2);
                ctx.fillStyle = player.color;
                ctx.fill();
                ctx.closePath();
                
                // 绘制玩家方向指示器
                if (joystick.isActive) {
                    ctx.beginPath();
                    ctx.moveTo(player.x, player.y);
                    ctx.lineTo(
                        player.x + joystick.x * 20, 
                        player.y + joystick.y * 20
                    );
                    ctx.strokeStyle = '#3498db';
                    ctx.lineWidth = 3;
                    ctx.stroke();
                    ctx.closePath();
                }
            }
            
            // 绘制网格背景
            function drawGrid() {
                ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
                ctx.lineWidth = 1;
                
                // 绘制垂直线
                for (let x = 0; x <= gameCanvas.width; x += 20) {
                    ctx.beginPath();
                    ctx.moveTo(x, 0);
                    ctx.lineTo(x, gameCanvas.height);
                    ctx.stroke();
                }
                
                // 绘制水平线
                for (let y = 0; y <= gameCanvas.height; y += 20) {
                    ctx.beginPath();
                    ctx.moveTo(0, y);
                    ctx.lineTo(gameCanvas.width, y);
                    ctx.stroke();
                }
            }
            
            // 更新游戏状态
            function updateGame() {
                if (joystick.isActive) {
                    // 根据摇杆输入移动玩家
                    player.x += joystick.x * player.speed;
                    player.y += joystick.y * player.speed;
                    
                    // 边界检查
                    player.x = Math.max(player.radius, Math.min(gameCanvas.width - player.radius, player.x));
                    player.y = Math.max(player.radius, Math.min(gameCanvas.height - player.radius, player.y));
                }
            }
            
            // 游戏循环
            function gameLoop() {
                updateGame();
                drawGame();
                requestAnimationFrame(gameLoop);
            }
            
            // 启动游戏循环
            gameLoop();
            
            // 处理摇杆移动
            function moveJoystickHandle(x, y) {
                // 计算相对于摇杆基座中心的位置
                const containerRect = joystickContainer.getBoundingClientRect();
                const centerX = containerRect.left + containerRect.width / 2;
                const centerY = containerRect.top + containerRect.height / 2;
                
                // 计算偏移量
                const deltaX = x - centerX;
                const deltaY = y - centerY;
                
                // 计算距离（确保摇杆不会超出基座范围）
                const distance = Math.min(joystick.maxDistance, Math.sqrt(deltaX * deltaX + deltaY * deltaY));
                
                // 计算角度
                const angle = Math.atan2(deltaY, deltaX);
                
                // 计算新的手柄位置
                const newX = Math.cos(angle) * distance;
                const newY = Math.sin(angle) * distance;
                
                // 更新手柄位置
                joystickHandle.style.transform = `translate(${newX}px, ${newY}px)`;
                
                // 计算标准化值（-1到1范围）
                joystick.x = distance > 0 ? newX / joystick.maxDistance : 0;
                joystick.y = distance > 0 ? newY / joystick.maxDistance : 0;
                
                // 更新输出显示
                updateOutputDisplay();
            }
            
            // 重置摇杆位置
            function resetJoystick() {
                joystickHandle.style.transform = 'translate(-50%, -50%)';
                joystick.x = 0;
                joystick.y = 0;
                joystick.isActive = false;
                updateOutputDisplay();
            }
            
            // 更新输出显示
            function updateOutputDisplay() {
                xValueElement.textContent = joystick.x.toFixed(2);
                yValueElement.textContent = joystick.y.toFixed(2);
                
                // 计算角度（0-360度）
                const angle = Math.atan2(joystick.y, joystick.x) * 180 / Math.PI;
                angleElement.textContent = angle.toFixed(1);
                
                // 计算强度（0-1）
                const intensity = Math.min(1, Math.sqrt(joystick.x * joystick.x + joystick.y * joystick.y));
                intensityElement.textContent = intensity.toFixed(2);
            }
            
            // 鼠标事件处理
            joystickContainer.addEventListener('mousedown', function(e) {
                joystick.isActive = true;
                moveJoystickHandle(e.clientX, e.clientY);
            });
            
            document.addEventListener('mousemove', function(e) {
                if (joystick.isActive) {
                    moveJoystickHandle(e.clientX, e.clientY);
                }
            });
            
            document.addEventListener('mouseup', function() {
                if (joystick.isActive) {
                    resetJoystick();
                }
            });
            
            // 触摸事件处理
            joystickContainer.addEventListener('touchstart', function(e) {
                e.preventDefault();
                joystick.isActive = true;
                moveJoystickHandle(e.touches[0].clientX, e.touches[0].clientY);
            });
            
            document.addEventListener('touchmove', function(e) {
                e.preventDefault();
                if (joystick.isActive) {
                    moveJoystickHandle(e.touches[0].clientX, e.touches[0].clientY);
                }
            });
            
            document.addEventListener('touchend', function(e) {
                e.preventDefault();
                if (joystick.isActive) {
                    resetJoystick();
                }
            });
            
            // 防止上下文菜单弹出
            joystickContainer.addEventListener('contextmenu', function(e) {
                e.preventDefault();
            });
            
            // 初始化输出显示
            updateOutputDisplay();
        });
    </script>
</body>
</html>